home *** CD-ROM | disk | FTP | other *** search
/ Aminet 22 / Aminet 22 (1997)(GTI - Schatztruhe)[!][Dec 1997].iso / Aminet / util / cdity / VesaDPMSPro.lha / VesaDPMSPro / VESADPMS.c < prev    next >
C/C++ Source or Header  |  1997-10-19  |  38KB  |  1,646 lines

  1. /*
  2.  *********** You need a tabulator width of 3 for a neat display !!! ***********
  3.  *                                                                                                        *
  4.  *    VESADPMS - Powersaving for VESA-compliant monitors and graphics cards        *
  5.  *                                                                                                        *
  6.  *    Why another one ? Maybe, VESA didn't make themselves too clear in their        *
  7.  * DPMS proposals. As an effect, my gfx-card/monitor combination has a basic    *
  8.  *    misinterpretation of the order, in which the blanking phases should come    *
  9.  *    up. The suspend command switches off, and the off command suspends...        *
  10.  *                                                                                                        *
  11.  *    Sadly, at this time no blanker supports a user-defined order of blanking.    *
  12.  *    Even MCP, where you can set the absolute blanking times, doesn't work for    *
  13.  *    some strange reason.                                                                            *
  14.  *                                                                                                        *
  15.  *    This blanker allows free combinations of the blanking order, to solve this    *
  16.  *    problem. It should work with any CyberGraphX gfx-card and monitor suppor-    *
  17.  *    ting DPMS.                                                                                        *
  18.  *                                                                                                        *
  19.  *    Thanks must go to:    Magnus Holmgren                        -    for CGXDPMS            *
  20.  *                                Stefan Sommerfeld/Michael Knoke    -    for MCP                *
  21.  *                                                                                                        *
  22.  * I hereby state, that VesaDPMS is NOT a rip-off of any of these or another    *
  23.  * DPMS blanker. No stolen code, maybe some inspiration. Apart from that, the    *
  24.  * included source code to CGXDPMS didn't convince me that much (the code for    *
  25.  * the custom CxObj is too large and unnecessarily calls some OS functions,    *
  26.  *    even one Intuition function, which is explicitly forbidden in the RKM !).    *
  27.  *                                                                                                        *
  28.  * WARNING:    This source code is for explanatory/tutorial purpose only !!!        *
  29.  *                Don't try to compile it with any C-Compiler, it won't work. The    *
  30.  *                reason for this are my currently unreleased private C programming    *
  31.  *                support functions, that allow fast, but functional programming of    *
  32.  *                applications. They are not finished yet, maybe I will never re-    *
  33.  *                lease them, even if they are finished. It took me too much work    *
  34.  *                to just give them away freely ...                                            *
  35.  *                                                                                                        *
  36.  ******************************************************************************
  37.  */
  38.  
  39. #include <pragma/exec_lib.h>
  40. #include <pragma/dos_lib.h>
  41. #include <pragma/intuition_lib.h>
  42. #include <pragma/gadtools_lib.h>
  43. #include <pragma/graphics_lib.h>
  44. #include <pragma/commodities_lib.h>
  45. #include <pragma/icon_lib.h>
  46. #include <pragma/utility_lib.h>
  47. #include <pragma/cybergraphics_lib.h>
  48. #include <clib/macros.h>
  49. #include <intuition/intuitionbase.h>
  50. #include <intuition/gadgetclass.h>
  51. #include <cybergraphics/cybergraphics.h>
  52. #include <stdlib.h>
  53. #include <string.h>
  54. #include <standardfuncprotos.h>
  55.  
  56. #define CUSTOM_ID        'CUST'
  57. #define SENDER1_ID    'SND1'
  58. #define SENDER2_ID    'SND2'
  59.  
  60. /********** Program parameter description **********/
  61. struct Pref
  62. {
  63.     struct Screen    *screen;        /* Screen from which to lend a ViewPort */
  64.     struct MsgPort    *cxport;        /* Message port for commodities communication */
  65.     ULONG                standby;        /* Seconds until entering standby mode */
  66.     ULONG                suspend;        /* Seconds until entering syspend mode */
  67.     ULONG                off;            /* Seconds until entering off mode */
  68.     ULONG                priority;    /* Priority of the Broker CxObject */
  69.     ULONG                wakeup;        /* InputEvent classes, that wake up from blanking */
  70.     ULONG                dpmslevel;    /* Current state of DPMS level */
  71.     ULONG                signal;        /* Signal for Custom CxObj, to indicate user activity */
  72.     char                *popkey;        /* User interface popup event combination */
  73.     char                *blankkey;    /* Immediate blank event combination */
  74. };
  75.  
  76. struct newPref
  77. {
  78.     ULONG    standby;            // Seconds until entering standby mode
  79.     ULONG    suspend;            // Seconds until entering suspend mode
  80.     ULONG    off;                // Seconds until entering off mode
  81.  
  82.     UBYTE check_standby;    // Standby mode enabled ?
  83.     UBYTE check_suspend;    // Suspend mode enabled ?
  84.     UBYTE check_off;        // Off mode enabled ?
  85.  
  86.     UBYTE mouse;            // Mouse wakes up ?
  87.     UBYTE disk;                // Disk wakes up ?
  88.     UBYTE tablet;            // Tablet wakes up ?
  89.     UBYTE key;                // unused, intended for keystroke
  90.     
  91.     UBYTE swtch;            // Screen switching allowed ?
  92.  
  93.     char *popkey;            // Key combination to pop up interface
  94.     char *blankkey;        // Key combination for immediate blanking
  95. };
  96.  
  97. /********** Global variables **********/
  98. //Global pointers
  99. extern struct IntuitionBase *IntuitionBase;
  100. struct Library *CyberGfxBase = NULL;
  101. CxObj *broker = NULL;
  102.  
  103. // Special macro for standard version string with MaxonDev4.0
  104. char *ver = AMIGAVERSION("VESADPMS", "1.2");
  105.  
  106. // ReadArgs stuff
  107. char *ratmpl = "CX_PRIORITY/N,CX_POPUP/T,PREFS=PREFERENCES/K";
  108. LONG arg[3] = {0, 1, 0};
  109. char preffile[128] = "SYS:Prefs/Presets/VesaDPMS.prefs";
  110.  
  111. // Custom CxObj signalling facilities
  112. ULONG lastsig = 0;
  113. ULONG listen =    ((1 << IECLASS_RAWKEY) | (1 << IECLASS_RAWMOUSE) | (1 << IECLASS_DISKINSERTED) | \
  114.                     (1 << IECLASS_DISKREMOVED) | (1 << IECLASS_NEWPOINTERPOS));
  115. BOOL active = FALSE, switchscreen = FALSE;
  116.  
  117. // Cluster of the program preferences variables, for easy usage
  118. struct Pref prefs =
  119. {
  120.     NULL,
  121.     NULL,
  122.     300,
  123.     600,
  124.     900,
  125.     0,
  126.     // Support keypress, mousemove, diskchange and graphic tablet
  127.     ((1 << IECLASS_RAWKEY) | (1 << IECLASS_RAWMOUSE) | (1 << IECLASS_DISKINSERTED) | \
  128.     (1 << IECLASS_DISKREMOVED) | (1 << IECLASS_NEWPOINTERPOS)),
  129.     DPMS_ON,
  130.     ~0,
  131.     NULL,        // MUST be allocated by allocPVec()
  132.     NULL        // dito
  133. };
  134. // To be filled in after argument parsing !
  135. struct newPref temp;
  136. struct IBox winbox = {0, 11, 0, 0};
  137.  
  138. // Font for the interface gadgets. Must be global. And, no, it's not hardcoded "topaz 8", that's
  139. // just for some useful initialization !
  140. char fontname[32] = "topaz.font";
  141. struct TextAttr ta =
  142. {
  143.     fontname,
  144.     8,
  145.     FS_NORMAL,
  146.     0
  147. };
  148.  
  149. // Remember the gadget addresses for keyboard shortcut handling
  150. #define INT_1_ID    0
  151. #define INT_2_ID    1
  152. #define INT_3_ID    2
  153. #define CB_1_ID    3
  154. #define CB_2_ID    4
  155. #define CB_3_ID    5
  156. #define CB_4_ID    6
  157. #define CB_5_ID    7
  158. #define CB_6_ID    8
  159. #define CB_7_ID    9
  160. #define STR_1_ID    10
  161. #define STR_2_ID    11
  162.  
  163. struct Gadget *gg[12];
  164.  
  165. /********** Application strings ready for localizing (one day ...) **********/
  166. #define TERMINATOR    0
  167. #define OPENCGXLIB    1
  168. #define OPENxxxLIB    2
  169. #define MEMORYPOOL    3
  170. #define NBNAME            4
  171. #define NBTITLE        5
  172. #define NBDESCR        6
  173. #define SIGNALLING    7
  174. #define EVENTS            8
  175. #define BLANKSCREEN    9
  176. #define NOTCYBER        10
  177. #define TICKER            11
  178. #define NOPARMS        12
  179. #define YESNO            13
  180. #define OK                14
  181. #define NUMBER1        15
  182. #define NUMBER2        16
  183. #define NUMBER3        17
  184. #define CHECKBOX1        18
  185. #define CHECKBOX2        19
  186. #define CHECKBOX3        20
  187. #define CHECKBOX4        21
  188. #define STRING1        22
  189. #define STRING2        23
  190. #define BUTTON1        24
  191. #define BUTTON2        25
  192. #define BUTTON3        26
  193. #define BUTTON4        27
  194. #define REALLYQUIT    28
  195. #define QUITCANCEL    29
  196. #define STILLWRONG    30
  197. #define LONGPATH        31
  198. #define CORRUPTPREFS    32
  199. #define WRITEERROR    33
  200. #define DEFPOPKEY        34
  201. #define DEFBLANKKEY    35
  202.  
  203. char *string[] =
  204. {
  205.     "Program terminated !\n",
  206.     "Could not open \"cybergraphics.library\".\n",
  207.     "Need an Amiga with OS 3.0 or better.\n",
  208.     "Not enough memory.\n",
  209.     "VesaDPMS Pro V1.2",
  210.     "VesaDPMS",
  211.     "Flexible Monitor Power Management",
  212.     "Could not establish message system.\n",
  213.     "Could not link into event handling.\n",
  214.     "Could not lock Default Public Screen.\n",
  215.     "Default Public Screen is not a CyberGraphX screen.\n",
  216.     "Could not set up \"timer.device\".\n",
  217.     "You did not set valid blanking intervals.\nOne of them must be at least 10 sec.\nDo you want to correct them ?",
  218.     "Yes, show interface|No, exit",
  219.     "««« OK »»»",
  220.     "St_andby :",
  221.     "Susp_end :",
  222.     "_Off     :",
  223.     "_Mouse :",
  224.     "_Disk  :",
  225.     "_Tablet:",
  226.     "S_witch:",
  227.     "_Popkey  :",
  228.     "_Blankkey:",
  229.     "_Quit",
  230.     "_Save",
  231.     "_Use",
  232.     "_Cancel",
  233.     "Do you really want to quit ?",
  234.     "Quit|Cancel",
  235.     "The blanking intervals you selected\nare still wrong !\n\nSelect OK to quit the program and\nREAD THE DOCUMENTATION !!!",
  236.     "The path for the preferences file is too long !\nIt must have less than 128 characters.\nI'm using defaults !",
  237.     "The preferences file is corrupt !\nCheck your settings and save again.\nI'm using defaults !",
  238.     "The preferences file could not be saved !\nThe path you supplied must be valid.\nAbout 2 kByte must be free on disk.",
  239.     "ctrl v",
  240.     "ctrl b",
  241.     NULL
  242. };
  243.  
  244. /********** Prototypes of external functions **********/
  245. void cx_custom_func(void);
  246.  
  247. /********** Prototypes of local functions **********/
  248. BOOL basicsetup(void);
  249. void basicshutdown(void);
  250. void arguments(struct WBStartup *wbstartup);
  251. BOOL extendedsetup(void);
  252. void extendedshutdown(void);
  253. BOOL showGUI(void);
  254. void waitforblank(void);
  255. BOOL startrequests(ULONG offset);
  256. struct Window *setupwindow(void);
  257. void shutdownwindow(struct Window *w);
  258. BOOL handlewinevents(struct IntuiMessage *imsg, BOOL *toggle);
  259. void settemp(void);
  260. void usetemp(struct Window *w);
  261. void savetemp(struct Window *w);
  262. BOOL newhotkey(void);
  263. void loadprefs(char *file);
  264. void saveprefs(char *file);
  265.  
  266. /********** Main function **********/
  267. void main(LONG argc, char **argv)
  268. {
  269.     if(basicsetup())
  270.     {
  271.         arguments(argc ? NULL : (struct WBStartup *) argv);
  272.         
  273.         if(extendedsetup())
  274.         {
  275.             waitforblank();
  276.         }
  277.         
  278.         extendedshutdown();
  279.     }
  280.     
  281.     basicshutdown();
  282.     
  283.     exit(RETURN_OK);
  284. }
  285.  
  286. /********** Local functions **********/
  287. BOOL basicsetup(void)
  288. {
  289.     register ULONG libs = MODULES | COMMODITY;
  290.     
  291.     CyberGfxBase = OpenLibrary("cybergraphics.library", 40);
  292.     if(CyberGfxBase)
  293.     {
  294.         setminversion(39);
  295.         if(openlibs(libs) == libs)
  296.         {
  297.             if(createMemPool(1024))
  298.             {
  299.                 return(TRUE);
  300.             }
  301.             else
  302.             {
  303.                 PutStr(string[MEMORYPOOL]);
  304.             }
  305.         }
  306.         else
  307.         {
  308.             PutStr(string[OPENxxxLIB]);
  309.         }
  310.     }
  311.     else
  312.     {
  313.         PutStr(string[OPENCGXLIB]);
  314.     }
  315.     
  316.     PutStr(string[TERMINATOR]);
  317.     
  318.     return(FALSE);
  319. }
  320.  
  321. void basicshutdown(void)
  322. {
  323.     CloseLibrary(CyberGfxBase);
  324.     closelibs(ALL_LIBS);
  325. }
  326.  
  327. void arguments(struct WBStartup *wbstartup)
  328. {
  329.     register struct RDArgs *rdargs;
  330.     register struct DiskObject *dop;
  331.     register UBYTE *cp, **tt;
  332.     register LONG val;
  333.     
  334.     if(wbstartup)
  335.     {
  336.         dop = openIcon(nextIcon(wbstartup));
  337.         if(dop)
  338.         {
  339.             tt = (UBYTE **) dop->do_ToolTypes;
  340.             
  341.             cp = FindToolType(tt, "CX_PRIORITY");
  342.             if(cp)
  343.             {
  344.                 if(StrToLong(cp, &val) > (LONG) 0)
  345.                 {
  346.                     prefs.priority = (ULONG) val;
  347.                 }
  348.             }
  349.             
  350.             cp = FindToolType(tt, "CX_POPUP");
  351.             if(cp)
  352.             {
  353.                 arg[1] = (LONG) (Stricmp(cp, "yes") ? FALSE : TRUE);
  354.             }
  355.             
  356.             cp = FindToolType(tt, "PREFERENCES");
  357.             if(cp)
  358.             {
  359.                 if(astrlen(cp) < 128)
  360.                 {
  361.                     strcpy(preffile, cp);
  362.                 }
  363.                 else
  364.                 {
  365.                     // Show errormessage and pop up
  366.                     infomessage(NULL, string[NBNAME], string[LONGPATH], string[OK]);
  367.                     arg[1] = TRUE;
  368.                 }
  369.             }
  370.             
  371.             closeIcon(dop);
  372.         }
  373.     }
  374.     else
  375.     {
  376.         rdargs = ReadArgs(ratmpl, arg, NULL);
  377.         if(rdargs)
  378.         {
  379.             if(arg[0])    // CX_PRIORITY
  380.             {
  381.                 prefs.priority = *((LONG *) arg[0]);
  382.             }
  383.             
  384.             // arg[1] (CX_POPUP) is a BOOL
  385.             
  386.             if(arg[2])    // PREFERENCES
  387.             {
  388.                 if(astrlen((char *) arg[2]) < 128)
  389.                 {
  390.                     strcpy(preffile, (char *) arg[2]);
  391.                 }
  392.                 else
  393.                 {
  394.                     // Show errormessage and pop up
  395.                     infomessage(NULL, string[NBNAME], string[LONGPATH], string[OK]);
  396.                     arg[1] = TRUE;
  397.                 }
  398.             }
  399.             
  400.             FreeArgs(rdargs);
  401.         }
  402.         else
  403.         {
  404.             PrintFault(IoErr(), NULL);
  405.         }
  406.     }
  407.     
  408.     loadprefs(preffile);
  409.     
  410.     if(prefs.standby)
  411.     {
  412.         prefs.standby = MAX(prefs.standby, 10);
  413.     }
  414.  
  415.     if(prefs.suspend)
  416.     {
  417.         prefs.suspend = MAX(prefs.suspend, 10);
  418.     }
  419.  
  420.     if(prefs.off)
  421.     {
  422.         prefs.off = MAX(prefs.off, 10);
  423.     }
  424.     
  425.     if(!prefs.popkey)
  426.     {
  427.         prefs.popkey = allocPVec(astrlen(string[DEFPOPKEY]) + 1);
  428.         if(prefs.popkey)
  429.         {
  430.             strcpy(prefs.popkey, string[DEFPOPKEY]);
  431.         }
  432.     }
  433.     
  434.     if(!prefs.blankkey)
  435.     {
  436.         prefs.blankkey = allocPVec(astrlen(string[DEFBLANKKEY]) + 1);
  437.         if(prefs.blankkey)
  438.         {
  439.             strcpy(prefs.blankkey, string[DEFBLANKKEY]);
  440.         }
  441.     }
  442.     
  443.     settemp();
  444. }
  445.  
  446. BOOL extendedsetup(void)
  447. {
  448.     prefs.screen = LockPubScreen(NULL);
  449.     if(!prefs.screen)
  450.     {
  451.         PutStr(string[BLANKSCREEN]);
  452.         return(FALSE);
  453.     }
  454.     
  455.     if(!IsCyberModeID(GetVPModeID(&(prefs.screen->ViewPort))))
  456.     {
  457.         PutStr(string[NOTCYBER]);
  458.         return(FALSE);
  459.     }
  460.     
  461.     prefs.signal = AllocSignal(~0);
  462.     prefs.cxport = CreateMsgPort();
  463.     
  464.     if((!prefs.cxport) || (prefs.signal == ~0))
  465.     {
  466.         PutStr(string[SIGNALLING]);
  467.         return(FALSE);
  468.     }
  469.     
  470.     if(newhotkey())
  471.     {
  472.         return(TRUE);
  473.     }
  474.     
  475.     PutStr(string[EVENTS]);
  476.     return(FALSE);
  477. }
  478.  
  479. void extendedshutdown(void)
  480. {
  481.     register struct Message *msg;
  482.     
  483.     FreeSignal(prefs.signal);
  484.     prefs.signal = ~0;
  485.     
  486.     DeleteCxObjAll(broker);
  487.     broker = NULL;
  488.     
  489.     if(prefs.cxport)
  490.     {
  491.         do
  492.         {
  493.             msg = GetMsg(prefs.cxport);
  494.             if(msg)
  495.             {
  496.                 ReplyMsg(msg);
  497.             }
  498.         }
  499.         while(msg);
  500.     }
  501.  
  502.     DeleteMsgPort(prefs.cxport);
  503.     prefs.cxport = NULL;
  504.     
  505.     UnlockPubScreen(NULL, prefs.screen);
  506. }
  507.  
  508. BOOL showGUI(void)
  509. {
  510.     struct Window *win;
  511.     register struct IntuiMessage *imsg;
  512.     register CxObj *msg;
  513.     ULONG rcvd, wait = SIGBREAKF_CTRL_C;
  514.     BOOL go = TRUE, rw = TRUE;
  515.     
  516.     win = setupwindow();
  517.     if(!win)
  518.     {
  519.         return(FALSE);
  520.     }
  521.     
  522.     wait |= (1 << win->UserPort->mp_SigBit);
  523.     wait |= (1 << prefs.cxport->mp_SigBit);
  524.     
  525.     while(go)
  526.     {
  527.         rcvd = Wait(wait);
  528.         
  529.         if(rcvd & SIGBREAKF_CTRL_C)
  530.         {
  531.             go = FALSE;
  532.             rw = FALSE;
  533.         }
  534.         
  535.         if(rcvd & (1 << win->UserPort->mp_SigBit))    // Window event
  536.         {
  537.             do
  538.             {
  539.                 imsg = GT_GetIMsg(win->UserPort);
  540.                 if(imsg)
  541.                 {
  542.                     go = handlewinevents(imsg, &rw);
  543.                     if(!rw)
  544.                     {
  545.                         // If the Quit gadget was clicked, exit immediately and leave all
  546.                         // pending messages to closeWindowSafely()
  547.                         imsg = NULL;
  548.                     }
  549.                 }
  550.             }
  551.             while(imsg);
  552.         }
  553.         
  554.         if(rcvd & (1 << prefs.cxport->mp_SigBit))
  555.         {
  556.             do
  557.             {
  558.                 msg = (CxObj *) GetMsg(prefs.cxport);
  559.                 if(msg)
  560.                 {
  561.                     if(CxMsgType(msg) == CXM_COMMAND)
  562.                     {
  563.                         switch(CxMsgID(msg))
  564.                         {
  565.                             case CXCMD_DISABLE:
  566.                             {
  567.                                 active = FALSE;
  568.                                 ActivateCxObj(broker, active);
  569.                             }
  570.                             break;
  571.                             
  572.                             case CXCMD_ENABLE:
  573.                             {
  574.                                 active = TRUE;
  575.                                 ActivateCxObj(broker, active);
  576.                             }
  577.                             break;
  578.                             
  579.                             case CXCMD_KILL:
  580.                             {
  581.                                 rw = FALSE;    // Leave program
  582.                             }
  583.                             case CXCMD_DISAPPEAR:
  584.                             {
  585.                                 go = FALSE;    // Leave GUI
  586.                             }
  587.                             default:
  588.                             break;
  589.                         }
  590.                     }
  591.                     
  592.                     ReplyMsg((struct Message *) msg);
  593.                 }
  594.             }
  595.             while(msg);
  596.         }
  597.     }
  598.     
  599.     shutdownwindow(win);
  600.     
  601.     return(rw);
  602. }
  603.  
  604. void waitforblank(void)
  605. {
  606.     register struct ViewPort *vp;
  607.     register CxMsg *msg;
  608.     struct TagItem cgxtags[] =
  609.     {
  610.         {SETVC_DPMSLevel, DPMS_ON},
  611.         {TAG_END, 0}
  612.     };
  613.     ULONG sigrcvd, msgtyp, msg_id, ticksig;
  614.     ULONG sigwait = SIGBREAKF_CTRL_C, immediate;
  615.     BOOL go = TRUE;
  616.     
  617.     ticksig = initTicker(UNIT_VBLANK);
  618.     if(!ticksig)
  619.     {
  620.         PutStr(string[TICKER]);
  621.         return;
  622.     }
  623.     
  624.     sigwait |= ticksig;
  625.     sigwait |= (1 << prefs.cxport->mp_SigBit);
  626.     sigwait |= (1 << prefs.signal);
  627.     
  628.     if(arg[1])
  629.     {
  630.         if(!showGUI())
  631.         {
  632.             closeTicker();
  633.             return;
  634.         }
  635.     }
  636.     
  637.     if(!startrequests(0))
  638.     {
  639.         closeTicker();
  640.         return;
  641.     }
  642.     
  643.     active = TRUE;
  644.     ActivateCxObj(broker, active);
  645.     
  646.     // Pre-initialize with a guaranteed value for additional safety
  647.     vp = &(prefs.screen->ViewPort);
  648.     
  649.     do
  650.     {
  651.         sigrcvd = Wait(sigwait);
  652.         
  653.         if(sigrcvd & SIGBREAKF_CTRL_C)
  654.         {
  655.             go = FALSE;
  656.         }
  657.         
  658.         if(sigrcvd & ticksig)
  659.         {
  660.             // Try to blank with the frontmost screen
  661.             vp = &(IntuitionBase->FirstScreen->ViewPort);
  662.             
  663.             // If not, try the Default Public Screen
  664.             if(!IsCyberModeID(GetVPModeID(vp)))
  665.             {
  666.                 // If switching screens is allowed, bring the Default PubScreen to front
  667.                 // Note, that this is very irritating, when working on a different screen,
  668.                 // so I make it an explicit switch to on.
  669.                 if(switchscreen)
  670.                 {
  671.                     ScreenToFront(prefs.screen);
  672.                 }
  673.                 
  674.                 vp = &(prefs.screen->ViewPort);
  675.             }
  676.             
  677.             switch(getUserData())
  678.             {
  679.                 case DPMS_STANDBY:
  680.                 {
  681.                     cgxtags[0].ti_Data = DPMS_STANDBY;
  682.                     CVideoCtrlTagList(vp, cgxtags);
  683.                     prefs.dpmslevel = DPMS_STANDBY;
  684.                 }
  685.                 break;
  686.                 
  687.                 case DPMS_SUSPEND:
  688.                 {
  689.                     cgxtags[0].ti_Data = DPMS_SUSPEND;
  690.                     CVideoCtrlTagList(vp, cgxtags);
  691.                     prefs.dpmslevel = DPMS_SUSPEND;
  692.                 }
  693.                 break;
  694.                 
  695.                 case DPMS_OFF:
  696.                 {
  697.                     cgxtags[0].ti_Data = DPMS_OFF;
  698.                     CVideoCtrlTagList(vp, cgxtags);
  699.                     prefs.dpmslevel = DPMS_OFF;
  700.                 }
  701.                 default:
  702.                 break;
  703.             }
  704.         }
  705.         
  706.         if(sigrcvd & (1 << prefs.signal))
  707.         {
  708.             stopTicker(0);
  709.             
  710.             if(prefs.dpmslevel != DPMS_ON)
  711.             {
  712.                 cgxtags[0].ti_Data = DPMS_ON;
  713.                 // Difficult to use "vp" again. But as the user didn't do anything until
  714.                 // now (blanking was on, so the user was off), it should still be valid.
  715.                 
  716.                 // 02/10/1997: This is definitely wrong ! If you use Commodores "Blanker"
  717.                 // together with VesaDPMS and switch off mouse events, "vp" is trash !
  718.                 // Thanks go to Stefan Hensen, for reporting the error !
  719.                 vp = &(IntuitionBase->FirstScreen->ViewPort);
  720.                 
  721.                 CVideoCtrlTagList(vp, cgxtags);
  722.                 prefs.dpmslevel = DPMS_ON;
  723.             }
  724.             
  725.             if(active)
  726.             {
  727.                 go = startrequests(0);
  728.             }
  729.         }
  730.         
  731.         if(sigrcvd & (1 << prefs.cxport->mp_SigBit))
  732.         {
  733.             do
  734.             {
  735.                 msg = (CxMsg *) GetMsg(prefs.cxport);
  736.                 if(msg)
  737.                 {
  738.                     msg_id = CxMsgID(msg);
  739.                     msgtyp = CxMsgType(msg);
  740.                     ReplyMsg((struct Message *) msg);
  741.                     
  742.                     stopTicker(0);
  743.                     if(prefs.dpmslevel != DPMS_ON)
  744.                     {
  745.                         cgxtags[0].ti_Data = DPMS_ON;
  746.                         vp = &(IntuitionBase->FirstScreen->ViewPort);
  747.                         CVideoCtrlTagList(vp, cgxtags);
  748.                         prefs.dpmslevel = DPMS_ON;
  749.                     }
  750.                     
  751.                     switch(msgtyp)
  752.                     {
  753.                         case CXM_IEVENT:
  754.                         {
  755.                             switch(msg_id)
  756.                             {
  757.                                 case SENDER1_ID:    // POPKEY
  758.                                 {
  759.                                     active = FALSE;
  760.                                     ActivateCxObj(broker, active);
  761.                                     go = showGUI();
  762.                                     active = go;
  763.                                     ActivateCxObj(broker, active);
  764.                                     if(active)
  765.                                     {
  766.                                         go = startrequests(0);
  767.                                     }
  768.                                 }
  769.                                 break;
  770.                                 
  771.                                 case SENDER2_ID:    // BLANKKEY
  772.                                 {
  773.                                     // Find the shortest blanking time. Ignore zero values !
  774.                                     immediate = ~0;
  775.                                     if(prefs.standby)
  776.                                     {
  777.                                         immediate = MIN(immediate, prefs.standby);
  778.                                     }
  779.                                     if(prefs.suspend)
  780.                                     {
  781.                                         immediate = MIN(immediate, prefs.suspend);
  782.                                     }
  783.                                     if(prefs.off)
  784.                                     {
  785.                                         immediate = MIN(immediate, prefs.off);
  786.                                     }
  787.                                     
  788.                                     if(immediate != ~0)
  789.                                     {
  790.                                         go = startrequests(immediate);
  791.                                     }
  792.                                 }
  793.                                 default:
  794.                                 break;
  795.                             }
  796.                         }
  797.                         break;
  798.                         
  799.                         case CXM_COMMAND:
  800.                         {
  801.                             switch(msg_id)
  802.                             {
  803.                                 case CXCMD_APPEAR:
  804.                                 {
  805.                                     active = FALSE;
  806.                                     ActivateCxObj(broker, active);
  807.                                     go = showGUI();
  808.                                     active = go;
  809.                                     ActivateCxObj(broker, active);
  810.                                     if(active)
  811.                                     {
  812.                                         go = startrequests(0);
  813.                                     }
  814.                                 }
  815.                                 break;
  816.                                 
  817.                                 case CXCMD_DISABLE:
  818.                                 {
  819.                                     active = FALSE;
  820.                                     ActivateCxObj(broker, active);
  821.                                 }
  822.                                 break;
  823.                                 
  824.                                 case CXCMD_ENABLE:
  825.                                 {
  826.                                     go = startrequests(0);
  827.                                     active = TRUE;
  828.                                     ActivateCxObj(broker, active);
  829.                                 }
  830.                                 break;
  831.                                 
  832.                                 case CXCMD_KILL:
  833.                                 {
  834.                                     go = FALSE;    // Leave program loop
  835.                                 }
  836.                                 break;
  837.                                 
  838.                                 case CXCMD_UNIQUE:    // User tried to start us a second time: POPUP
  839.                                 {
  840.                                     active = FALSE;
  841.                                     ActivateCxObj(broker, active);
  842.                                     go = showGUI();
  843.                                     active = go;
  844.                                     ActivateCxObj(broker, active);
  845.                                     if(active)
  846.                                     {
  847.                                         go = startrequests(0);
  848.                                     }
  849.                                 }
  850.                                 default:
  851.                                 break;
  852.                             }
  853.                         }
  854.                         default:
  855.                         break;
  856.                     }
  857.                 }
  858.             }
  859.             while(msg);
  860.         }
  861.     }
  862.     while(go);
  863.     
  864.     closeTicker();
  865.     active = FALSE;
  866.     ActivateCxObj(broker, active);
  867. }
  868.  
  869. BOOL startrequests(ULONG offset)
  870. {
  871.     BOOL ok = FALSE;
  872.     
  873.     // Skip levels with blanking time set to zero seconds
  874.     if(prefs.standby)
  875.     {
  876.         ok |= startTicker(prefs.standby - offset, 0, DPMS_STANDBY);
  877.     }
  878.     
  879.     if(prefs.suspend)
  880.     {
  881.         ok |= startTicker(prefs.suspend - offset, 0, DPMS_SUSPEND);
  882.     }
  883.     
  884.     if(prefs.off)
  885.     {
  886.         ok |= startTicker(prefs.off - offset, 0, DPMS_OFF);
  887.     }
  888.     
  889.     // Could any request be started ?
  890.     if(!ok)
  891.     {
  892.         // Is at least one time set ? Then it's an error !
  893.         if(prefs.standby || prefs.suspend || prefs.off)
  894.         {
  895.             PutStr(string[TICKER]);
  896.         }
  897.         else    // Just a user's mistake
  898.         {
  899.             if(infomessage(NULL, string[NBNAME], string[NOPARMS], string[YESNO]))
  900.             {
  901.                 ok = showGUI();
  902.                 if((prefs.standby < 10) && (prefs.suspend < 10) && (prefs.off < 10))
  903.                 {
  904.                     infomessage(NULL, string[NBNAME], string[STILLWRONG], string[OK]);
  905.                     ok = FALSE;
  906.                 }
  907.             }
  908.         }
  909.     }
  910.     
  911.     return(ok);
  912. }
  913.  
  914. struct Window *setupwindow(void)
  915. {
  916.     // Get tricky to save stack: fully initialize one taglist,
  917.     // then shorten the other ones: look at the TAG_MORE trick !
  918.     struct TagItem chktags1[] =
  919.     {
  920.         {GTCB_Checked,        temp.check_standby},
  921.         {GTCB_Scaled,        TRUE},
  922.         {GT_Underscore,    (ULONG) '_'},
  923.         {TAG_END, 0}
  924.     };
  925.     struct TagItem chktags2[] =
  926.     {
  927.         {GTCB_Checked,        temp.check_suspend},
  928.         {TAG_MORE,             (ULONG) &chktags1[1]}
  929.     };
  930.     struct TagItem chktags3[] =
  931.     {
  932.         {GTCB_Checked,        temp.check_off},
  933.         {TAG_MORE,             (ULONG) &chktags1[1]}
  934.     };
  935.     struct TagItem chktags4[] =
  936.     {
  937.         {GTCB_Checked,        temp.mouse},
  938.         {TAG_MORE,             (ULONG) &chktags1[1]}
  939.     };
  940.     struct TagItem chktags5[] =
  941.     {
  942.         {GTCB_Checked,        temp.disk},
  943.         {TAG_MORE,             (ULONG) &chktags1[1]}
  944.     };
  945.     struct TagItem chktags6[] =
  946.     {
  947.         {GTCB_Checked,        temp.tablet},
  948.         {TAG_MORE,             (ULONG) &chktags1[1]}
  949.     };
  950.     struct TagItem chktags7[] =
  951.     {
  952.         {GTCB_Checked,        temp.swtch},
  953.         {TAG_MORE,             (ULONG) &chktags1[1]}
  954.     };
  955.     struct TagItem numtags1[] =
  956.     {
  957.         {GTIN_Number,        temp.standby},
  958.         {GA_Disabled,        FALSE},
  959.         {TAG_MORE,             (ULONG) &chktags1[2]}
  960.     };
  961.     struct TagItem numtags2[] =
  962.     {
  963.         {GTIN_Number,        temp.suspend},
  964.         {GA_Disabled,        FALSE},
  965.         {TAG_MORE,             (ULONG) &chktags1[2]}
  966.     };
  967.     struct TagItem numtags3[] =
  968.     {
  969.         {GTIN_Number,        temp.off},
  970.         {GA_Disabled,        FALSE},
  971.         {TAG_MORE,             (ULONG) &chktags1[2]}
  972.     };
  973.     struct TagItem strtags1[] =
  974.     {
  975.         {GTST_String,        (ULONG) temp.popkey},
  976.         {TAG_MORE,             (ULONG) &chktags1[2]}
  977.     };
  978.     struct TagItem strtags2[] =
  979.     {
  980.         {GTST_String,        (ULONG) temp.blankkey},
  981.         {TAG_MORE,             (ULONG) &chktags1[2]}
  982.     };
  983.     struct TagItem *buttags = &chktags1[2];
  984.     struct NewGadget ng[16] =
  985.     {
  986.         {12,  1,  6,  2, string[NUMBER1], &ta, 1,    PLACETEXT_LEFT, (APTR) INTEGER_KIND, numtags1},
  987.         {12,  3,  6,  2, string[NUMBER2], &ta, 2,    PLACETEXT_LEFT, (APTR) INTEGER_KIND, numtags2},
  988.         {12,  5,  6,  2, string[NUMBER3], &ta, 3,    PLACETEXT_LEFT, (APTR) INTEGER_KIND, numtags3},
  989.         {19,  1,  3,  2, NULL,               &ta, 4,    0,                     (APTR) CHECKBOX_KIND, chktags1},
  990.         {19,  3,  3,  2, NULL,               &ta, 5,    0,                     (APTR) CHECKBOX_KIND, chktags2},
  991.         {19,  5,  3,  2, NULL,               &ta, 6,    0,                     (APTR) CHECKBOX_KIND, chktags3},
  992.         
  993.         {32,  1,  3,  2, string[CHECKBOX1], &ta,  7, PLACETEXT_LEFT, (APTR) CHECKBOX_KIND, chktags4},
  994.         {32,  3,  3,  2, string[CHECKBOX2], &ta,  8, PLACETEXT_LEFT, (APTR) CHECKBOX_KIND, chktags5},
  995.         {32,  5,  3,  2, string[CHECKBOX3], &ta,  9, PLACETEXT_LEFT, (APTR) CHECKBOX_KIND, chktags6},
  996.         {32,  7,  3,  2, string[CHECKBOX4], &ta, 10, PLACETEXT_LEFT, (APTR) CHECKBOX_KIND, chktags7},
  997.         
  998.         {12,  8, 10,  2, string[STRING1], &ta, 11, PLACETEXT_LEFT, (APTR) STRING_KIND, strtags1},
  999.         {12, 10, 10,  2, string[STRING2], &ta, 12, PLACETEXT_LEFT, (APTR) STRING_KIND, strtags2},
  1000.         
  1001.         {24, 10, 11,  2, string[BUTTON1], &ta, 13, PLACETEXT_IN, (APTR) BUTTON_KIND, buttags},
  1002.         
  1003.         { 1, 13, 11,  2, string[BUTTON2], &ta, 14,            PLACETEXT_IN, (APTR) BUTTON_KIND, buttags},
  1004.         {13, 13, 11,  2, string[BUTTON3], &ta, 15,            PLACETEXT_IN, (APTR) BUTTON_KIND, buttags},
  1005.         {25, 13, 11,  2, string[BUTTON4], &ta, LASTGADGET, PLACETEXT_IN, (APTR) BUTTON_KIND, buttags}
  1006.     };
  1007.     struct IBox bevel[] =
  1008.     {
  1009.         {  0,  0, 36, 15},    // Main box
  1010.         {  1,  7, 20,  0},    // Separate integer from string
  1011.         {  1, 12, 34,  0},    // Separate buttons from rest
  1012.         { 23,  9, 12,  0},    // Separate checkbox from button
  1013.         { 22,  1,  0, 10}        // Separate left from right
  1014.     };
  1015.     struct Window *w;
  1016.     struct Gadget *g;
  1017.     ULONG flags = (WFLG_ACTIVATE | WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | \
  1018.                         WFLG_RMBTRAP | WFLG_SIMPLE_REFRESH);
  1019.     ULONG idcmp = (IDCMP_REFRESHWINDOW | IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY |\
  1020.                         BUTTONIDCMP | CHECKBOXIDCMP | INTEGERIDCMP | STRINGIDCMP);
  1021.     UWORD x, y;
  1022.     
  1023.     numtags1[1].ti_Data = temp.check_standby ? FALSE : TRUE;
  1024.     numtags2[1].ti_Data = temp.check_suspend ? FALSE : TRUE;
  1025.     numtags3[1].ti_Data = temp.check_off ? FALSE : TRUE;
  1026.     
  1027.     // Get rid of "topaz 8", if you have set a better DefaultFont
  1028.     getFontAttr(getDefFontSize(&x, &y), &ta);
  1029.     
  1030.     g = layoutGadgets(prefs.screen, ng, x, y, 2, 2, 1, 1);
  1031.     if(g)
  1032.     {
  1033.         w = openWin(string[NBNAME], flags, idcmp, prefs.screen, g, &winbox);
  1034.         if(w)
  1035.         {
  1036.             gg[INT_1_ID] = ng[0].ng_UserData;
  1037.             gg[INT_2_ID] = ng[1].ng_UserData;
  1038.             gg[INT_3_ID] = ng[2].ng_UserData;
  1039.             
  1040.             gg[CB_1_ID] = ng[3].ng_UserData;
  1041.             gg[CB_2_ID] = ng[4].ng_UserData;
  1042.             gg[CB_3_ID] = ng[5].ng_UserData;
  1043.             gg[CB_4_ID] = ng[6].ng_UserData;
  1044.             gg[CB_5_ID] = ng[7].ng_UserData;
  1045.             gg[CB_6_ID] = ng[8].ng_UserData;
  1046.             gg[CB_7_ID] = ng[9].ng_UserData;
  1047.             
  1048.             gg[STR_1_ID] = ng[10].ng_UserData;
  1049.             gg[STR_2_ID] = ng[11].ng_UserData;
  1050.             
  1051.             bevelBox(w, &bevel[0], x, y, TRUE,  BBFT_RIDGE);
  1052.             bevelBox(w, &bevel[1], x, y, FALSE, BBFT_BUTTON);
  1053.             bevelBox(w, &bevel[2], x, y, FALSE, BBFT_BUTTON);
  1054.             bevelBox(w, &bevel[3], x, y, FALSE, BBFT_BUTTON);
  1055.             bevelBox(w, &bevel[4], x, y, FALSE, BBFT_BUTTON);
  1056.             
  1057.             return(w);
  1058.         }
  1059.         
  1060.         FreeGadgets(g);
  1061.     }
  1062.     
  1063.     return(NULL);
  1064. }
  1065.  
  1066. void shutdownwindow(struct Window *w)
  1067. {
  1068.     struct Gadget *g = w->FirstGadget;
  1069.     
  1070.     // Note: openWin() and closeWindowSafely() are automatically aware of shared
  1071.     // window message ports. Too bad, I have not released them yet. ¦^)
  1072.     
  1073.     removeBBox(w);
  1074.     closeWindowSafely(w);
  1075.     if(g)
  1076.     {
  1077.         FreeGadgets(g);
  1078.     }
  1079. }
  1080.  
  1081. BOOL handlewinevents(struct IntuiMessage *imsg, BOOL *toggle)
  1082. {
  1083.     register struct Window *win;
  1084.     register struct Gadget *gad;
  1085.     register ULONG class;
  1086.     register UWORD code;
  1087.     char *newpop, *newblank;
  1088.     ULONG result;
  1089.     BOOL rw = TRUE;
  1090.     
  1091.     win    = imsg->IDCMPWindow;
  1092.     gad    = imsg->IAddress;
  1093.     class    = imsg->Class;
  1094.     code    = imsg->Code;
  1095.     
  1096.     GT_ReplyIMsg(imsg);
  1097.     
  1098.     switch(class)
  1099.     {
  1100.         case IDCMP_GADGETUP:
  1101.         {
  1102.             switch(gad->GadgetID)
  1103.             {
  1104.                 case 1:    // Standby
  1105.                 {
  1106.                     GT_GetGadgetAttrs(gad, win, NULL, GTIN_Number, &result, TAG_END);
  1107.                     temp.standby = result;
  1108.                 }
  1109.                 break;
  1110.                 
  1111.                 case 2:    // Suspend
  1112.                 {
  1113.                     GT_GetGadgetAttrs(gad, win, NULL, GTIN_Number, &result, TAG_END);
  1114.                     temp.suspend = result;
  1115.                 }
  1116.                 break;
  1117.                 
  1118.                 case 3:    // Off
  1119.                 {
  1120.                     GT_GetGadgetAttrs(gad, win, NULL, GTIN_Number, &result, TAG_END);
  1121.                     temp.off = result;
  1122.                 }
  1123.                 break;
  1124.                 
  1125.                 case 4:    // CheckStandby
  1126.                 {
  1127.                     GT_GetGadgetAttrs(gad, win, NULL, GTCB_Checked, &result, TAG_END);
  1128.                     GT_SetGadgetAttrs(gg[INT_1_ID], win, NULL, GA_Disabled, result ? FALSE : TRUE, TAG_END);
  1129.                     temp.check_standby = (UBYTE) result;
  1130.                 }
  1131.                 break;
  1132.                 
  1133.                 case 5:    // CheckSuspend
  1134.                 {
  1135.                     GT_GetGadgetAttrs(gad, win, NULL, GTCB_Checked, &result, TAG_END);
  1136.                     GT_SetGadgetAttrs(gg[INT_2_ID], win, NULL, GA_Disabled, result ? FALSE : TRUE, TAG_END);
  1137.                     temp.check_suspend = (UBYTE) result;
  1138.                 }
  1139.                 break;
  1140.                 
  1141.                 case 6:    // CheckOff
  1142.                 {
  1143.                     GT_GetGadgetAttrs(gad, win, NULL, GTCB_Checked, &result, TAG_END);
  1144.                     GT_SetGadgetAttrs(gg[INT_3_ID], win, NULL, GA_Disabled, result ? FALSE : TRUE, TAG_END);
  1145.                     temp.check_off = (UBYTE) result;
  1146.                 }
  1147.                 break;
  1148.                 
  1149.                 case 7:    // Mouse
  1150.                 {
  1151.                     GT_GetGadgetAttrs(gad, win, NULL, GTCB_Checked, &result, TAG_END);
  1152.                     temp.mouse = (UBYTE) result;
  1153.                 }
  1154.                 break;
  1155.                 
  1156.                 case 8:    // Disk
  1157.                 {
  1158.                     GT_GetGadgetAttrs(gad, win, NULL, GTCB_Checked, &result, TAG_END);
  1159.                     temp.disk = (UBYTE) result;
  1160.                 }
  1161.                 break;
  1162.                 
  1163.                 case 9:    // Tablet
  1164.                 {
  1165.                     GT_GetGadgetAttrs(gad, win, NULL, GTCB_Checked, &result, TAG_END);
  1166.                     temp.tablet = (UBYTE) result;
  1167.                 }
  1168.                 break;
  1169.                 
  1170.                 case 10:    // Switch
  1171.                 {
  1172.                     GT_GetGadgetAttrs(gad, win, NULL, GTCB_Checked, &result, TAG_END);
  1173.                     temp.swtch = (UBYTE) result;
  1174.                 }
  1175.                 break;
  1176.                 
  1177.                 case 11:    // Popkey
  1178.                 {
  1179.                     GT_GetGadgetAttrs(gad, win, NULL, GTST_String, &result, TAG_END);
  1180.                     if(stricmp((char *) result, temp.popkey))
  1181.                     {
  1182.                         newpop = allocPVec(strlen((char *) result) + 1);
  1183.                         if(newpop)
  1184.                         {
  1185.                             strcpy(newpop, (char *) result);
  1186.                             freePVec(temp.popkey);
  1187.                             temp.popkey = newpop;
  1188.                         }
  1189.                     }
  1190.                 }
  1191.                 break;
  1192.                 
  1193.                 case 12:    // Blankkey
  1194.                 {
  1195.                     GT_GetGadgetAttrs(gad, win, NULL, GTST_String, &result, TAG_END);
  1196.                     if(stricmp((char *) result, temp.blankkey))
  1197.                     {
  1198.                         newblank = allocPVec(strlen((char *) result) + 1);
  1199.                         if(newblank)
  1200.                         {
  1201.                             strcpy(newblank, (char *) result);
  1202.                             freePVec(temp.blankkey);
  1203.                             temp.blankkey = newblank;
  1204.                         }
  1205.                     }
  1206.                 }
  1207.                 break;
  1208.                 
  1209.                 case 13:    // Quit
  1210.                 {
  1211.                     *toggle = (infomessage(win, string[NBTITLE], string[REALLYQUIT], string[QUITCANCEL]) ? FALSE : TRUE);
  1212.                     rw = FALSE;
  1213.                 }
  1214.                 break;
  1215.                 
  1216.                 case 14:    // Save
  1217.                 {
  1218.                     if((prefs.popkey != temp.popkey) || (prefs.blankkey != temp.blankkey))
  1219.                     {
  1220.                         *toggle = newhotkey();
  1221.                     }
  1222.                     savetemp(win);
  1223.                     rw = FALSE;
  1224.                 }
  1225.                 break;
  1226.                 
  1227.                 case 15:    // Use
  1228.                 {
  1229.                     if((prefs.popkey != temp.popkey) || (prefs.blankkey != temp.blankkey))
  1230.                     {
  1231.                         *toggle = newhotkey();
  1232.                     }
  1233.                     usetemp(win);
  1234.                     rw = FALSE;
  1235.                 }
  1236.                 break;
  1237.                 
  1238.                 case LASTGADGET:    // Cancel
  1239.                 {
  1240.                     if(prefs.popkey != temp.popkey)
  1241.                     {
  1242.                         freePVec(temp.popkey);
  1243.                     }
  1244.                     if(prefs.blankkey != temp.blankkey)
  1245.                     {
  1246.                         freePVec(temp.blankkey);
  1247.                     }
  1248.                     settemp();
  1249.                     rw = FALSE;
  1250.                 }
  1251.                 default:
  1252.                 break;
  1253.             }
  1254.         }
  1255.         break;
  1256.         
  1257.         case IDCMP_REFRESHWINDOW:
  1258.         {
  1259.             GT_BeginRefresh(win);
  1260.             
  1261.             drawBBox(win);
  1262.             
  1263.             GT_EndRefresh(win, TRUE);
  1264.         }
  1265.         break;
  1266.         
  1267.         case IDCMP_CLOSEWINDOW:
  1268.         {
  1269.             rw = FALSE;
  1270.         }
  1271.         break;
  1272.         
  1273.         case IDCMP_VANILLAKEY:
  1274.         {
  1275.             switch(code | 32)
  1276.             {
  1277.                 case TAB_KEY | 32:
  1278.                 {
  1279.                     ActivateGadget(gg[STR_1_ID], win, NULL);
  1280.                 }
  1281.                 break;
  1282.                 
  1283.                 case 'a':    // stAndby
  1284.                 {
  1285.                     GT_SetGadgetAttrs(gg[CB_1_ID], win, NULL, GTCB_Checked, TRUE, TAG_END);
  1286.                     GT_SetGadgetAttrs(gg[INT_1_ID], win, NULL, GA_Disabled, FALSE, GTIN_Number, temp.standby, TAG_END);
  1287.                     ActivateGadget(gg[INT_1_ID], win, NULL);
  1288.                 }
  1289.                 break;
  1290.                 
  1291.                 case 'b':    // Blankkey
  1292.                 {
  1293.                     ActivateGadget(gg[STR_2_ID], win, NULL);
  1294.                 }
  1295.                 break;
  1296.                 
  1297.                 case 'c':    // Cancel
  1298.                 {
  1299.                     if(prefs.popkey != temp.popkey)
  1300.                     {
  1301.                         freePVec(temp.popkey);
  1302.                     }
  1303.                     if(prefs.blankkey != temp.blankkey)
  1304.                     {
  1305.                         freePVec(temp.blankkey);
  1306.                     }
  1307.                     settemp();
  1308.                     rw = FALSE;
  1309.                 }
  1310.                 break;
  1311.                 
  1312.                 case 'd':    // Disk
  1313.                 {
  1314.                     temp.disk = temp.disk ? 0 : 1;
  1315.                     GT_SetGadgetAttrs(gg[CB_5_ID], win, NULL, GTCB_Checked, temp.disk, TAG_END);
  1316.                 }
  1317.                 break;
  1318.                 
  1319.                 case 'e':    // suspEnd
  1320.                 {
  1321.                     GT_SetGadgetAttrs(gg[CB_2_ID], win, NULL, GTCB_Checked, TRUE, TAG_END);
  1322.                     GT_SetGadgetAttrs(gg[INT_2_ID], win, NULL, GA_Disabled, FALSE, GTIN_Number, temp.suspend, TAG_END);
  1323.                     ActivateGadget(gg[INT_2_ID], win, NULL);
  1324.                 }
  1325.                 break;
  1326.                 
  1327.                 case 'm':    // Mouse
  1328.                 {
  1329.                     temp.mouse = temp.mouse ? 0 : 1;
  1330.                     GT_SetGadgetAttrs(gg[CB_4_ID], win, NULL, GTCB_Checked, temp.mouse, TAG_END);
  1331.                 }
  1332.                 break;
  1333.                 
  1334.                 case 'o':    // Off
  1335.                 {
  1336.                     GT_SetGadgetAttrs(gg[CB_3_ID], win, NULL, GTCB_Checked, TRUE, TAG_END);
  1337.                     GT_SetGadgetAttrs(gg[INT_3_ID], win, NULL, GA_Disabled, FALSE, GTIN_Number, temp.off, TAG_END);
  1338.                     ActivateGadget(gg[INT_3_ID], win, NULL);
  1339.                 }
  1340.                 break;
  1341.                 
  1342.                 case 'p':    // Popkey
  1343.                 {
  1344.                     ActivateGadget(gg[STR_1_ID], win, NULL);
  1345.                 }
  1346.                 break;
  1347.                 
  1348.                 case 'q':    // Quit
  1349.                 {
  1350.                     *toggle = (infomessage(win, string[NBTITLE], string[REALLYQUIT], string[QUITCANCEL]) ? FALSE : TRUE);
  1351.                     rw = FALSE;
  1352.                 }
  1353.                 break;
  1354.                 
  1355.                 case 's':    // Save
  1356.                 {
  1357.                     if((prefs.popkey != temp.popkey) || (prefs.blankkey != temp.blankkey))
  1358.                     {
  1359.                         *toggle = newhotkey();
  1360.                     }
  1361.                     savetemp(win);
  1362.                     rw = FALSE;
  1363.                 }
  1364.                 break;
  1365.                 
  1366.                 case 't':    // Tablet
  1367.                 {
  1368.                     temp.tablet = temp.tablet ? 0 : 1;
  1369.                     GT_SetGadgetAttrs(gg[CB_6_ID], win, NULL, GTCB_Checked, temp.tablet, TAG_END);
  1370.                 }
  1371.                 break;
  1372.                 
  1373.                 case 'u':    // Use
  1374.                 {
  1375.                     if((prefs.popkey != temp.popkey) || (prefs.blankkey != temp.blankkey))
  1376.                     {
  1377.                         *toggle = newhotkey();
  1378.                     }
  1379.                     usetemp(win);
  1380.                     rw = FALSE;
  1381.                 }
  1382.                 break;
  1383.                 
  1384.                 case 'w':    // sWitch
  1385.                 {
  1386.                     // Toggle SWITCHSCREENS
  1387.                     temp.swtch = temp.swtch ? 0 : 1;
  1388.                     GT_SetGadgetAttrs(gg[CB_7_ID], win, NULL, GTCB_Checked, temp.swtch, TAG_END);
  1389.                 }
  1390.                 default:
  1391.                 break;
  1392.             }
  1393.         }
  1394.         break;
  1395.         
  1396.         default:
  1397.         break;
  1398.     }
  1399.     
  1400.     return(rw);
  1401. }
  1402.  
  1403. void settemp(void)
  1404. {
  1405.     temp.standby = prefs.standby;
  1406.     temp.suspend = prefs.suspend;
  1407.     temp.off         = prefs.off;
  1408.     
  1409.     temp.check_standby = temp.standby ? 1 : 0;
  1410.     temp.check_suspend = temp.suspend ? 1 : 0;
  1411.     temp.check_off         = temp.off ? 1 : 0;
  1412.     
  1413.     temp.mouse    = ((1 << IECLASS_RAWMOUSE) & prefs.wakeup) ? 1 : 0;
  1414.     temp.disk    = (((1 << IECLASS_DISKINSERTED) | (1 << IECLASS_DISKREMOVED)) & prefs.wakeup) ? 1 : 0;
  1415.     temp.tablet    = ((1 << IECLASS_NEWPOINTERPOS) & prefs.wakeup) ? 1 : 0;
  1416.     temp.key        = ((1 << IECLASS_RAWKEY) & prefs.wakeup) ? 1 : 0;
  1417.     
  1418.     temp.swtch = switchscreen ? 1 : 0;
  1419.     
  1420.     temp.popkey   = prefs.popkey;
  1421.     temp.blankkey = prefs.blankkey;
  1422. }
  1423.  
  1424. void usetemp(struct Window *w)
  1425. {
  1426.     prefs.standby = temp.check_standby ? temp.standby : 0;
  1427.     prefs.suspend = temp.check_suspend ? temp.suspend : 0;
  1428.     prefs.off      = temp.check_off ? temp.off : 0;
  1429.     
  1430.     switchscreen = temp.swtch;
  1431.     
  1432.     prefs.wakeup = (1 << IECLASS_RAWKEY);
  1433.     prefs.wakeup |= temp.mouse ? (1 << IECLASS_RAWMOUSE) : 0;
  1434.     prefs.wakeup |= temp.disk ? ((1 << IECLASS_DISKINSERTED) | (1 << IECLASS_DISKREMOVED)) : 0;
  1435.     prefs.wakeup |= temp.tablet ? (1 << IECLASS_NEWPOINTERPOS) : 0;
  1436.     prefs.wakeup |= temp.key ? (1 << IECLASS_RAWKEY) : 0;
  1437.     
  1438.     prefs.popkey = temp.popkey;
  1439.     prefs.blankkey = temp.blankkey;
  1440.     
  1441.     // Finally remember the window position
  1442.     snapshotwindow(w, &winbox);
  1443.     // Leave sizing to layoutGadgets()
  1444.     winbox.Width = 0;
  1445.     winbox.Height = 0;
  1446. }
  1447.  
  1448. void savetemp(struct Window *w)
  1449. {
  1450.     usetemp(w);
  1451.     saveprefs(preffile);
  1452. }
  1453.  
  1454. // This function is for lazyness only. It's slower than only replacing the filter objects,
  1455. // but needs less code than an additional replacing function, that removes the old and
  1456. // inserts a new filter.
  1457. BOOL newhotkey(void)
  1458. {
  1459.     CxObj *custom, *filter1, *filter2, *sender1, *sender2, *trans1, *trans2;
  1460.     struct NewBroker nb =
  1461.     {
  1462.         NB_VERSION,
  1463.         string[NBNAME],
  1464.         string[NBTITLE],
  1465.         string[NBDESCR],
  1466.         NBU_UNIQUE | NBU_NOTIFY,
  1467.         COF_SHOW_HIDE,
  1468.         prefs.priority,
  1469.         prefs.cxport,
  1470.         0
  1471.     };
  1472.     
  1473.     DeleteCxObjAll(broker);
  1474.     
  1475.     broker = CxBroker(&nb, NULL);
  1476.     if(broker)
  1477.     {
  1478.         custom    = CxCustom(&cx_custom_func, CUSTOM_ID);
  1479.         filter1    = CxFilter(temp.popkey);
  1480.         filter2    = CxFilter(temp.blankkey);
  1481.         sender1    = CxSender(prefs.cxport, SENDER1_ID);
  1482.         sender2    = CxSender(prefs.cxport, SENDER2_ID);
  1483.         trans1    = CxTranslate(NULL);
  1484.         trans2    = CxTranslate(NULL);
  1485.         
  1486.         if(custom && filter1 && filter2 && sender1 && sender2)
  1487.         {
  1488.             // Here the single CxObjects are linked together. Note, that the custom CxObject
  1489.             // directly Signal()s to the application to avoid additional overhead.
  1490.             
  1491.             AttachCxObj(broker, custom);        //                +-> CUSTOM  >---------------+
  1492.             AttachCxObj(broker, filter1);        //                |                                     |
  1493.             AttachCxObj(broker, filter2);        //    BROKER >-+-> FILTER1 >-+-> SENDER1 >-+-> VesaDPMS
  1494.             AttachCxObj(filter1, sender1);    //                |                  |                 |
  1495.             AttachCxObj(filter2, sender2);    //                |            (TRANS1/2)             |
  1496.             AttachCxObj(filter1, trans1);        //                |                  |                 |
  1497.             AttachCxObj(filter2, trans2);        //                +-> FILTER2 >-+-> SENDER2 >-+
  1498.             
  1499.             return(TRUE);
  1500.         }
  1501.         
  1502.         DeleteCxObj(trans2);
  1503.         DeleteCxObj(trans1);
  1504.         DeleteCxObj(sender2);
  1505.         DeleteCxObj(sender1);
  1506.         DeleteCxObj(filter2);
  1507.         DeleteCxObj(filter1);
  1508.         DeleteCxObj(custom);
  1509.         DeleteCxObj(broker);
  1510.     }
  1511.     
  1512.     return(FALSE);
  1513. }
  1514.  
  1515. /*
  1516.  Preferences structure: Standby time            4 bytes
  1517.                                  Suspend time            4 bytes
  1518.                                  Off time                    4 bytes
  1519.                                  CX_PRIORITY                4 bytes
  1520.                                  Wakeup bits                4 bytes
  1521.                                  Switch button state    2 bytes
  1522.                                  X/Y window position    4 bytes
  1523.                                  Length of popkey        4 bytes
  1524.                                  Popkey                    variable length (0 - 256 bytes) !
  1525.                                  Length of blankkey    4 bytes
  1526.                                  Blankkey                    variable length (0 - 256 bytes) !
  1527.  */
  1528. void loadprefs(char *file)
  1529. {
  1530.     register UBYTE *str, *oldpop;
  1531.     register BPTR fh;
  1532.     ULONG buffer[5];
  1533.     ULONG size;
  1534.     
  1535.     fh = Open(file, MODE_OLDFILE);
  1536.     if(fh)
  1537.     {
  1538.         // Read in standby, suspend, off, priority and wakeup
  1539.         if(FRead(fh, buffer, 4, 5) == 5)
  1540.         {
  1541.             // Read in Switch gadget state
  1542.             if(FRead(fh, &switchscreen, 2, 1))
  1543.             {
  1544.                 // Read in former window position
  1545.                 if(FRead(fh, &winbox, 4, 1))
  1546.                 {
  1547.                     // Read in size of popkey
  1548.                     if(FRead(fh, &size, 4, 1))
  1549.                     {
  1550.                         if(size > 256)
  1551.                         {
  1552.                             Close(fh);
  1553.                             infomessage(NULL, string[NBTITLE], string[CORRUPTPREFS], string[OK]);
  1554.                             return;
  1555.                         }
  1556.                         
  1557.                         str = allocPVec(size);
  1558.                         if(str)
  1559.                         {
  1560.                             if(FRead(fh, str, size, 1))
  1561.                             {
  1562.                                 oldpop = prefs.popkey;
  1563.                                 prefs.popkey = str;
  1564.                             
  1565.                                 // Read in size of blankkey
  1566.                                 if(FRead(fh, &size, 4, 1))
  1567.                                 {
  1568.                                     if(size > 256)
  1569.                                     {
  1570.                                         Close(fh);
  1571.                                         infomessage(NULL, string[NBTITLE], string[CORRUPTPREFS], string[OK]);
  1572.                                         prefs.popkey = oldpop;
  1573.                                         return;
  1574.                                     }
  1575.                                     
  1576.                                     str = allocPVec(size);
  1577.                                     if(str)
  1578.                                     {
  1579.                                         if(FRead(fh, str, size, 1))
  1580.                                         {
  1581.                                             freePVec(prefs.blankkey);
  1582.                                             freePVec(oldpop);
  1583.                                             prefs.blankkey = str;
  1584.                                             CopyMem(buffer, &(prefs.standby), 20);
  1585.                                             Close(fh);
  1586.                                             return;
  1587.                                         }
  1588.                                     }
  1589.                                 }
  1590.                             }
  1591.                             
  1592.                             freePVec(str);
  1593.                         }
  1594.                     }
  1595.                 }
  1596.             }
  1597.         }
  1598.         
  1599.         Close(fh);
  1600.         infomessage(NULL, string[NBTITLE], string[CORRUPTPREFS], string[OK]);
  1601.         prefs.popkey = oldpop;
  1602.     }
  1603. }
  1604.  
  1605. void saveprefs(char *file)
  1606. {
  1607.     register BPTR fh;
  1608.     ULONG size;
  1609.     
  1610.     fh = Open(file, MODE_NEWFILE);
  1611.     if(fh)
  1612.     {
  1613.         if(FWrite(fh, &(prefs.standby), 4, 5) == 5)
  1614.         {
  1615.             if(FWrite(fh, &switchscreen, 2, 1))
  1616.             {
  1617.                 if(FWrite(fh, &winbox, 2, 2) == 2)
  1618.                 {
  1619.                     size = astrlen(prefs.popkey) + 1;
  1620.                     
  1621.                     if(FWrite(fh, &size, 4, 1))
  1622.                     {
  1623.                         if(FWrite(fh, prefs.popkey, size, 1))
  1624.                         {
  1625.                             size = astrlen(prefs.blankkey) + 1;
  1626.                             
  1627.                             if(FWrite(fh, &size, 4, 1))
  1628.                             {
  1629.                                 if(FWrite(fh, prefs.blankkey, size, 1))
  1630.                                 {
  1631.                                     Close(fh);
  1632.                                     return;
  1633.                                 }
  1634.                             }
  1635.                         }
  1636.                     }
  1637.                 }
  1638.             }
  1639.         }
  1640.     }
  1641.     
  1642.     Close(fh);
  1643.     infomessage(NULL, string[NBTITLE], string[WRITEERROR], string[OK]);
  1644. }
  1645.  
  1646.